home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Developer CD v2.1
/
Amiga Developer CD v2.1.iso
/
DevInfo
/
DeviceDevelopment
/
NSD-CommandSpecs
< prev
next >
Wrap
Text File
|
1997-05-15
|
21KB
|
544 lines
$Id: NSD-CommandSpecs 1.6 1997/05/15 18:09:56 heinz Exp $
NSD Command Space
=================
As of January 1st, 1996, Amiga International, Inc. reserves two
ranges in the set of command values for future enhancements. Only
commands as specified by Amiga International, Inc. may be used
here. It is illegal for a device developer to randomly "add" custom
commands or command features in the reserved are!
There are 65536 command values possible with io_Command:
$0000 - $3FFF old style and 3rd party commands
$4000 - $7FFF RESERVED AREA!
$8000 - $BFFF old style and 3rd party commands
$C000 - $FFFF RESERVED AREA!
To say it again: Commands in the reserved areas may only be
assigned and specified by Amiga International, Inc.. Any "custom"
implementation of these commands or other commands in these
reserved areas is illegal and violates programming standards!
Design Basis
============
A device driver is REQUIRED to return IOERR_NOCMD on any command it
does not understand. This requirement is very old. It has been
documented publically in 1991 already. If the device understands a
command but the underlying HW can not handle it, IOERR_NOCMD should
not be returned. IOERR_NOCMD should be an indicator for
non supported, i.e., non-implemented, commands of the device, not
for those that just cannot be executed due to environment
constraints.
What will new style commands do for you?
========================================
With old style devices it is impossible to find out about the type
of device you are accessing. You don't know if the command set is
serial.device like or trackdisk like. You don't know either what
kind of request structure is appropriate. New style commands will
let you query the device for its capabilities. As capabilities are
added to a device, device users can use more features transparently
without compatibility hacks.
There are two types of new style commands. "General" commands are
the same for all new style devices. Depending on the device type
there are device specific commands, too.
General commands will be defined in the range $4000-$7FFF, device
specific commands are using the range $C000-$FFFF. It is illegal to
use a device specific command before using the general commands to
confirm the device's capabilities.
With a new style device, you can be sure that no 3rd party command
will interact with the standard meaning of all the device's
commands as documented for V40 of the OS.
Basic requirements
==================
Let's make a quick list about the most basic requirements for any new
style device. Keep it in mind when reading on.
- IOERR_NOCMD support
- no redefinition of standard V40 or reserved commands
- no 3rd party commands in reserved areas
- NSCMD_DEVICEQUERY is supported
- lib_IdString must contain the name, version, and creation
date of the device and any other readable information to make
unique identification of a device for 3rd party command use
possible.
- Check mn_Length of the request on OpenDevice() for the minimum
required length
Some devices may have additional requirements. These will be listed
in the sub document "NSD-DeviceSpecifics".
Device Types
============
There are various types of devices in the V40 OS. audio.device is
substantially different from serial.device, just like input.device
is different from a SANA-II device like a2065.device. NSD does not
want to describe the semantics behind each type of device. It puts
the different V40 command sets needed for different types of
devices into useful groups and tags these groups with an NSD device
type identifier. This is to make sure that the existing standard
V40 command set in each group is not redefined arbitrarily. The
NSD device type identifier does not refer to specific
functionality. User's of an NSD device must be able to fall back on
these standard commands when they are implemented and get results
that match usage of the respective V40 devices listed below. When a
device is "like" a certain type mentioned, the emphasis is put on
the the command set being alike to allow for grouping. Here is an
annotated list of NSD device types, naming the respective V40
devices and headers which define the command numbers that may not be
redefined if they are implemented.
#define NSDEVTYPE_UNKNOWN 0 /* No suitable category, anything */
Any device that does not fit in a group mentioned below. Think
hard if you really need this category. Most likely you want an
exact identification then as described below to make sure what
you got. This category is dangerous as you can't say anything
about most of the old style command set without an exact NSD
identification.
V40 Command Numbers: 1-8
#define NSDEVTYPE_GAMEPORT 1 /* like gameport.device */
gameport.device <devices/gameport.h>
V40 Command Numbers: 1-13
#define NSDEVTYPE_TIMER 2 /* like timer.device */
timer.device <devices/timer.h>
V40 Command Numbers: 1-11
#define NSDEVTYPE_KEYBOARD 3 /* like keyboard.device */
keyboard.device <devices/keyboard.h>
V40 Command Numbers: 1-13
#define NSDEVTYPE_INPUT 4 /* like input.device */
input.device <devices/input.h>
V40 Command Numbers: 1-16
#define NSDEVTYPE_TRACKDISK 5 /* like trackdisk.device */
trackdisk.device <devices/trackdisk.h>
scsi.device <devices/scsidisk.h>
cd.device <devices/cd.h>
mfm.device similar to <devices/trackdisk.h>
V40 Command Numbers: 1-23,28-29,32-46,
$8002-$8005,$8009-$800B,$8010-$8011
The command sets of these three devices are sufficiently alike
to put them under a single label. It is expected that the
device interface for devices like these converge over time.
#define NSDEVTYPE_CONSOLE 6 /* like console.device */
console.device <devices/console.h>
V40 Command Numbers: 1-12
#define NSDEVTYPE_SANA2 7 /* A >=SANA2R2 networking device */
any SANA-II device <devices/sana2.h> (from the SANA-II archive)
V40 Command Numbers: 1-26
#define NSDEVTYPE_AUDIO 8 /* like audio.device */
audio.device <devices/audio.h>
V40 Command Numbers: 1-14,32
#define NSDEVTYPE_CLIPBOARD 9 /* like clipboard.device */
clipboard.device <devices/clipboard.h>
V40 Command Numbers: 1-12
#define NSDEVTYPE_PRINTER 10 /* like printer.device */
printer.device <devices/printer.h>
V40 Command Numbers: 1-12
#define NSDEVTYPE_SERIAL 11 /* like serial.device */
serial.device <devices/serial.h>
V40 Command Numbers: 1-11
#define NSDEVTYPE_PARALLEL 12 /* like parallel.device */
parallel.device <devices/parallel.h>
V40 Command Numbers: 1-10
The meaning of "No Command Redefinition"
========================================
An NSD device of a certain type is not allowed to redefine any V40
command or any command from the NSD reserved ranges. Each NSD
device type as described above groups the corresponding V40 devices
with similar command sets. Each of these devices has an
established, documented, and implemented set of commands with
documented meaning. An NSD device must always handle all these
commands, if implemented, like the respective V40 device or like
the set of V40 devices for that NSD device type. It is not
acceptable if a CMD_READ suddenly turns into functionality of
CMD_WRITE or if HD_SCSICMD will suddenly be like a TD_EJECT. If you
find, e.g., HD_SCSICMD or CD_INFO in the supported command list of a
NSDEVTYPE_TRACKDISK device, you shall be sure that these commands
behave like the V40 commands of the respective devices would
behave. Note that if you find one command supported for an NSD
device type, this does not mean that other commands for that NSD
device type are necessarily supported. Check for the command set
that you need.
For the common eight usable Exec standard commands, intentionally
no distinction is made between different V40 devices which may fall
under the same NSD device type. The device I/O operations should be
consistent and uniform according to the RKM and NSD does not try to
differentiate between possible execution differences for the Exec
standard commands. Because of this requirement for consistency and
uniformity, the standard Exec commands obviously may not be
redefined arbitrarily either. If an Exec standard command is
implemented in a device, the implementation must not deviate from
the specification for that device type or common usage for that
command.
All command slots that are not part of the V40 command set for the
respective devices under the NSD device types or of the reserved
NSD areas are free to be used for 3rd party extensions. NSD neither
defines nor restricts their usage. From the NSD perspective, the
meaning of any implemented 3rd party command is undefined. The user
software is responsible for an exact device identification then to
use 3rd party commands safely via the device's lib_IDString as
described below.
General commands
================
At the moment there is just a single new style general command:
#define NSCMD_DEVICEQUERY 0x4000
It is required for all new style devices.
You set up io_Data and io_Length pointing to a struct
NSDeviceQueryResult below. You must clear SizeAvailable and set up
DevQueryFormat before sending the command to the device. A new
style device will set up the data in the buffer appropriately. If
the command executed successfully the returned io_Actual value must
be greater than zero and equal to the SizeAvailable value that has
been set by the device. As with device usage in general, an
io_Actual value that is alrger than the passed in io_Length value
should be considered an error. The device may only be considered a
new style device if these conditions are met. And only in this case
the results of the query may be considered valid.
struct NSDeviceQueryResult
{
/*
** Standard information
*/
ULONG DevQueryFormat; /* this is type 0 */
ULONG SizeAvailable; /* bytes available */
/*
** Common information (READ ONLY!)
*/
UWORD DeviceType; /* what the device does */
UWORD DeviceSubType; /* depends on the main type */
UWORD *SupportedCommands; /* 0 terminated list of cmd's */
/* May be extended in the future! Check SizeAvailable! */
};
The device will fill in the struct NSDeviceQueryResult with read
only data for the caller. All data must remain constant and valid
as long as the device is open. After CloseDevice(), all bets are
off.
SizeAvailable
Tells you how much of the structure contains valid data. It
is measured in bytes. Do not try to use fields in the
structure that are not fully included in the SizeAvailable
range. SizeAvailable must include SupportedCommands for any
successful query. So the minimum valid value is 16.
DeviceType
This tells you about the NSD type of device you are
accessing. The type names often match existing devices in
AmigaOS. If a device returns such a type, the device must
be able to at least handle all the documented features for
V40 of the operating system that the respective original
device has. If the NSD device type refers to a group of V40
devices, at least the basic command subset as for the
device named by the NSD device type shall be handled.
Note well that while all the documented features for an
implemented command shall be handled, it is permissible
to return error codes or appropriate dummy returns for non
existing features in the NSD device as long as the handling
conforms to the original specification.
If an old style or new style command cannot be supported in
a compatible manner, the device is required to return
IOERR_NOCMD for safety reasons. Modification of the
specification is not allowed. Add a 3rd party command if
needed.
It is illegal to "reuse" command numbers of documented
standard commands that cannot be supported for other
purposes. E.g. a device driver of type NSDEVTYPE_TRACKDISK
that does not support TD_GETGEOMETRY and uses this command
for different functionality can never be a new style device
and may not support new style commands.
It is also illegal to use the results of an
NSCMD_DEVICEQUERY without testing DeviceType first.
The NSD device types are listed and explained above in the
section "Device Types".
More types will be defined by Amiga International, Inc. as
necessary and requested. Each NSD device type represents a
certain command set that the device must handle. If the
type does not match a device that does exist in OS V40, the
exact requirements are defined below or in
"NSD-DeviceSpecifics". Note that some DeviceType entries
may cover multiple types of devices, so you have to check
the documentation carefully, when considering the standard
command set for a specific type.
DeviceSubType
There might be special incarnations of a device with
special capabilities beyond the standard set. At the moment
none are defined and a device is required to return 0 here.
As extensions that are marked by this field have to be
upwards compatible, this field need not be tested by users
who don't need any special capabilities beyond the standard
set. Otherwise it must be tested first.
SupportedCommands
This points to a 0 terminated list of io_Command values
that are supported by the device. This list must contain
all legal command values, old style, new style, and special
3rd party commands that are understood by the device and do
not cause an IOERR_NOCMD right away.
You might notice the similarity to the SANA2-R2 (S2R2) S2_DEVICEQUERY
command. It is intentional.
If you are developing software that needs to use 3rd party
commands, you must try an *exact* 3rd party device identification
via the lib_IdString in the device base and reject all devices that
you don't know for a new style device.
New Style Check in C
====================
A code fragment that could help you set up a new device query
follows.
struct IOStdReq *io;
struct NSDeviceQueryResult nsdqr;
LONG error;
BOOL newstyle = FALSE;
BOOL does64bit = FALSE;
BOOL doesETD64bit = FALSE;
UWORD *cmdcheck;
struct MsgPort *replyport;
...
/* See important *CAVEAT* below! */
io = CreateIORequest(replyport, sizeof(struct IOStdReq) + 128);
/* Add error checking in production code! */
...
nsdqr.SizeAvailable = 0;
nsdqr.DevQueryFormat = 0;
io->io_Command = NSCMD_DEVICEQUERY;
io->io_Length = sizeof(nsdqr);
io->io_Data = (APTR)&nsdqr;
error = DoIO((struct IORequest *)io);
if((!error) &&
(io->io_Actual >= 16) &&
(io->io_Actual <= sizeof(nsdqr)) &&
(nsdqr.SizeAvailable == io->io_Actual))
{
/* Ok, this must be a new style device */
newstyle = TRUE;
/* Device specific code follows here */
if(nsdqr.DeviceType == NSDEVTYPE_TRACKDISK)
{
/* Is it safe to use 64 bits with this driver? We can reject
* bad mounts pretty easily via this check!
*/
for(cmdcheck = nsdqr.SupportedCommands;
*cmdcheck;
cmdcheck++)
{
if(*cmdcheck == NSCMD_TD_READ64)
{
/* This trackdisk style device supports the basic
* 64 bit command set without returning IOERR_NOCMD!
*/
does64bit = TRUE;
} /* if */
if(*cmdcheck == NSCMD_ETD_READ64)
{
/* This trackdisk style device supports the extended
* 64 bit command set without returning IOERR_NOCMD!
* According to specs, this implies does64bit == TRUE!
*/
doesETD64bit = TRUE;
} /* if */
} /* for */
} /* if */
} /* if */
*** CAVEAT ***: There are some noteworthy points about this code
fragment:
The check of io_Actual filters out anything that is obviously
wrong. An NSD device may not return less than the minimum query
structure and of course it may not try to return more than the
buffer space available.
Error checking for request allocation has been left out for
brevity. Obviously, production code should contain decent error
checking code.
This code fragment uses a pointer to a struct IOStdReq to do the
checks. Unfortunately, using a request of this size may result in
severe problems with certain devices like SANA-II devices, which
need a larger request structure. A current device should at minimum
check in its OpenDevice() code if the passed in request is of at
least the minimum required size to work with via its mn_Length
field and fail to open if it isn't. This is a simple but effective
paranoia check with the effect that surely broken request
structures will be rejected right away. Unfortunately most devices
don't do that check. Two basic assumptions can be relevant here:
1. The trusting assumption
You simply use the type and size of request structure
appropriate for the type of device you intend to use and
assume that the user did not give you the wrong type
of device. This may fail and result in a system crash.
2. The safer assumption
You use the type of request for the device type your are
expecting (or an IOStdReq for a general check) with an
extra 128 zeroed bytes when opening and checking a device.
This will be very safe as current devices are required to
check the minimum request length before opening
successfully. So any wrong type of device will not cause
problems here unless it both
- uses a really strange long request that is
referenced on OpenDevice() time
and
- does not implement the required mn_Length check
You only need that one larger request for the check on
opening the device. Afterwards you know what you are
working with and can use reasonably sized requests.
Obviously we cannot approve of the trusting assumption, because
device access should be as safe as possible. So we require you to
implement the safer assumption. Again, the basic idea behind this
is that you should always strive to make device access as safe as
possible. Some little things like validating the request structure
on OpenDevice() will increase stability of the device system a lot
at hardly any extra cost. Play it as safe as you can. The user
might have some messed up code accessing the device!
It is wise to avoid writing devices that need arguments set up in
the request structure for an OpenDevice() call. If you have to
write a device like this, validate the request structure well
and fail gracefully if you don't find the arguments needed.
It is valid and strongly suggested behaviour for a device to reject
all new style commands except NSCMD_DEVICEQUERY with IOERR_NOCMD
unless the caller executed a valid and successful NSCMD_DEVICEQUERY
at least once before. This is intentionally stretching the meaning
of IOERR_NOCMD to protect old software.
Recommended use
===============
Anyone who wants to take advantage of the new style device
interface should do this:
- OpenDevice() as described above
- Try a NSCMD_DEVICEQUERY as described above
- If successful according to the rules mentioned above,
use the commands as listed in "SupportedCommands".
- Otherwise it must be an old style device. Hope and pray that
you got what you wanted.
Note: The above description and the code fragment shown assumes
that you use OpenDevice() with a freshly created and appropriately
initialised request structure. If you intend to reuse a previously
used request structure for another OpenDevice() to make a general
query, you should set at least the following fields to zero before
calling OpenDevice(): io_Actual, io_Length, io_Data, io_Offset.
It is strongly recommended to always do a query with a freshly set
up request structure.
Old Style and/or 3rd party vs. NSD
==================================
NSD conforming devices may only be identified via
NSCMD_DEVICEQUERY. NSD does not make any judgements about old style
devices or their usage. NSD does not make any judgements about
3rd party features within the NSD framework. If NSD is not
available in a device, you are free to use other functionality as
you see fit for the underlying old style device. If an NSD feature
is not available, you are free to use other functionality not
conflicting with the NSD specification.
*** EOT ***